-- NewbieDungeonM
-- Created by chengb Jun/4/2015
-- 新手关卡

module("NewbieDungeonM", package.seeall);

-- 配置表
local newbieDungeonTable = {};
local elemsByDungeonId = {};

-- 内部函数声明
local whenEnterNewbieDungeon;

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    elemsByDungeonId = {};

    -- 转换配置表
    newbie_dungeon_CSV = get_newbie_dungeon_CSV();
    for i = 1, #newbie_dungeon_CSV do
        local id = newbie_dungeon_CSV[i].id;
        newbieDungeonTable[id] = newbie_dungeon_CSV[i];

        -- 根据迷宫编号存放元素
        local dungeonId = newbie_dungeon_CSV[i].dungeon_id;
        if elemsByDungeonId[dungeonId] == nil then
            elemsByDungeonId[dungeonId]= {};
        end
        table.insert(elemsByDungeonId[dungeonId], id)
    end

    newbie_dungeon_CSV = {};
end

-- 模块初始化
function init()
    loadCsv();
    
    EventMgr.removeAll("NewbieDungeonM");
    
    -- 关注玩家进入指引关卡的事件
    EventMgr.register("NewbieDungeonM", event.ENTER_NEWBIE_DUNGEON,  function(layer)
        whenEnterNewbieDungeon(layer);
    end);
end

-- 是否是新手关卡
function isNewbieDungeon(dungeonId)
    local newbieList = table.keys(elemsByDungeonId);
    return table.indexOf(newbieList, dungeonId) ~= -1;
end

-- 是否在新手关卡中
function isInNewbieDungeon()
    if not DungeonM.isInDungeon() then
        return false;
    end

    local dungeonId = DungeonM.getDungeonId();
    if not isNewbieDungeon(dungeonId) then
        return false;
    end

    return true;
end

-- 打开妖精的铁笼
function openPixyCage(pos)
    local grid = DungeonM.getGridByPos(pos);
    if grid.state == GRID_STATE_DISABLE then
        -- 格子已经失效
        trace("NewbieDungeonM", "格子(%d)已失效", pos);
        return false;
    end

    if grid.type ~= GRID_TYPE_PIXY_CAGE then
        -- 不是妖精的铁笼
        trace("NewbieDungeonM", "格子(%d)不是妖精的铁笼", pos);
        return false;
    end

    -- 标记格子失效
    grid:changeState(GRID_STATE_DISABLE);

    -- 将格子转换成小妖精
    local elemDbase = DungeonM.queryElement(grid.element, "dbase");
    local toElement = elemDbase.trans_element;
    local toClass = DungeonM.queryElement(toElement, "class");
    local para = { ["class"] = toClass, ["element"] = toElement };
    DungeonM.transformGrid(toClass, pos, GRID_STATE_OPEN, para);

    DungeonLogM.addLog(string.format("格子%d转成元素%d", pos, toElement));

    return true;
end

-- 向小妖精索要物品
function askForItems(pos)
    -- 尝试完成成就：拯救小精灵
    EventMgr.fire(event.RESCUE_PIXY_ACHIEVE, { ["pos"] = pos, });
    return true;
end

-- 放走小妖精
function rescuePixy(pos)
    local grid = DungeonM.getGridByPos(pos);
    if grid.state == GRID_STATE_DISABLE then
        -- 格子已经失效
        trace("NewbieDungeonM", "格子(%d)已失效", pos);
        return false;
    end

    if grid.type ~= GRID_TYPE_PIXY then
        -- 不是妖精的铁笼
        trace("NewbieDungeonM", "格子(%d)不是小妖精", pos);
        return false;
    end

    -- 标记格子失效
    grid:changeState(GRID_STATE_DISABLE);

    -- 标记解救过小妖精的楼层
    local layer = DungeonM.currentLayer();
    DungeonM.setDungeonMixedField("has_recued_pixy", layer);

    -- 抛出拯救小精灵的事件
    EventMgr.fire(event.RESCUE_PIXY, { ["pos"] = pos, });

    -- 尝试完成成就：拯救小精灵
    EventMgr.fire(event.RESCUE_PIXY_ACHIEVE, { ["pos"] = pos, });
    return true;
end

-- 装置重弩
function installBow(pos)
    local grid = DungeonM.getGridByPos(pos);
    if grid.state == GRID_STATE_DISABLE then
        -- 格子已经失效
        trace("NewbieDungeonM", "格子(%d)已失效", pos);
        return false;
    end

    if grid.type ~= GRID_TYPE_RUSTY_BOW then
        -- 不是生锈的重弩
        trace("NewbieDungeonM", "格子(%d)不是生锈的重弩", pos);
        return false;
    end

    -- 检查是否有所需道具
    local dbase = DungeonM.query(grid.class, "dbase");
    local propertyId = dbase.property_id;
    if type(propertyId) == "number" then
        if ItemM.getAmount(ME.user, propertyId) <= 0 then
            trace("NewbieDungeonM", "无法装置重弩，没有所需道具！");
            return false;
        end

        ItemM.costAmount(ME.user, propertyId, 1);
    end

    -- 标记格子失效
    grid:changeState(GRID_STATE_DISABLE);

    -- 转换格子
    local toElement = dbase.trans_element;
    local toClass = DungeonM.queryElement(toElement, "class");
    local para = { ["class"] = toClass, ["element"] = toElement };
    DungeonM.transformGrid(toClass, pos, GRID_STATE_OPEN, para);
    return true;
end

-- 是否营救过小妖精
function hasResuedPixy()
    return type(DungeonM.getDungeonMixedField("has_recued_pixy")) == "number";
end

-- 是否往妖精之井投入了妖精的钱币
function hasInputDemonCoin()
    return type(DungeonM.getDungeonMixedField("has_input_demon_coin")) == "number";
end

-- 往妖精之井投放妖精的钱币
function doPixyWellEvent(pos)
    local grid = DungeonM.getGridByPos(pos);
    if grid.state == GRID_STATE_DISABLE then
        -- 格子已经失效
        trace("NewbieDungeonM", "格子(%d)已失效", pos);
        return false;
    end

    if grid.type ~= GRID_TYPE_PIXY_WELL then
        -- 不是妖精之井
        trace("NewbieDungeonM", "格子(%d)不是妖精之井", pos);
        return false;
    end

    local dbase = DungeonM.queryElement(grid.element, "dbase");
    local classId;
    if type(dbase) == "table" and type(dbase["need_property"]) == "number" then
        classId = dbase["need_property"];
        if ItemM.getAmount(ME.user, classId) <= 0 then
            trace("NewbieDungeonM", "包裹中没有妖精的钱币！");
            return false;
        end
    end

    if classId then
        -- 扣除妖精的钱币
        ItemM.costAmount(ME.user, classId, 1);
    end

    -- 记录一下
    DungeonM.setDungeonMixedField("has_input_demon_coin", 1);

    -- 执行奖励
    local eventBonus = FormulaM.invoke("CALC_PIXY_WELL_BONUS", ME.user);

    -- 执行奖励
    BuildingBonusM.doEvent(pos, false, false);

    -- 抛出通用建筑奖励事件
    EventMgr.fire(event.COMM_BUILDING_BONUS, {
        ["pos"]   = pos,
        ["type"]  = GRID_TYPE_PIXY_WELL,
        ["bonus"] = eventBonus,
    });

    return true;
end

-- 往妖精之井投放金币
function throwCoinToWell(pos, optionIndex)
    local grid = DungeonM.getGridByPos(pos);
    if grid.state == GRID_STATE_DISABLE then
        -- 格子已经失效
        trace("NewbieDungeonM", "格子(%d)已失效", pos);
        return false;
    end

    if grid.type ~= GRID_TYPE_PIXY_WELL then
        -- 不是妖精之井
        trace("NewbieDungeonM", "格子(%d)不是妖精之井", pos);
        return false;
    end

    local dbase = DungeonM.queryElement(grid.element, "dbase");
    if type(dbase) == "table" and type(dbase["need_property"]) == "number" then
        if ItemM.getAmount(ME.user, dbase["need_property"]) > 0 then
            trace("NewbieDungeonM", "包裹中有妖精的钱币，不应该投放金币！");
            return false;
        end
    end

    local arr = FormulaM.invoke("CALC_PIXY_WELL_COIN_OPTIONS");
    if optionIndex < 1 or optionIndex > #arr then
        trace("NewbieDungeonM", "无法投放金币，选项(%d)不存在。", optionIndex);
        return false;
    end

    -- 标记格子失效
    grid:changeState(GRID_STATE_DISABLE);

    -- 执行奖励
    local bonusList = FormulaM.invoke("CALC_PIXY_WELL_BONUS2", ME.user, optionIndex)
    for _, bonus in pairs(bonusList) do
        BonusM.doBonus(bonus, "pixy_throw_coin");
    end

    -- 抛出投放金币的事件
    EventMgr.fire(event.PIXY_THROW_COIN, { ["pos"] = pos, ["bonus"] = bonusList,
        ["optionIndex"] = optionIndex,});
    return true;
end

-- 统计新手关卡首次奖励
function statNewbieFirstBonus(path)
    local record = ME.user.dbase:query("newbie_first_bonus", {});
    record[path] = TRUE;
    ME.user.dbase:set("newbie_first_bonus", record);

    printTable(record, "newbie_first_bonus字段更新为");
end

-- 判断是否是新手关卡首次奖励
function isFirstNewbieBonus(path)
    local record = ME.user.dbase:query("newbie_first_bonus", {});
    return record[path] ~= TRUE;
end

-- 开启石匣
function openStoneBox(pos)
    local grid = DungeonM.getGridByPos(pos);
    if grid.state == GRID_STATE_DISABLE then
        -- 格子已经失效
        trace("NewbieDungeonM", "格子(%d)已失效", pos);
        return false;
    end

    if grid.type ~= GRID_TYPE_STONE_BOX then
        trace("NewbieDungeonM", "格子(%d)不是隐蔽的石匣。", pos);
        return false;
    end

    -- 如果配置了需求道具，需要扣除
    local dbase = DungeonM.queryElement(grid.element, "dbase");
    if type(dbase) == "table" then
        if type(dbase["need_property"]) == "number"  then
            if ItemM.getAmount(ME.user, dbase["need_property"]) > 0 then
                ItemM.costAmount(ME.user, dbase["need_property"], 1);
            end
        elseif type(dbase["need_property"]) == "table"  then
            for _, classId in pairs(dbase["need_property"]) do
                if ItemM.getAmount(ME.user, classId) > 0 then
                    ItemM.costAmount(ME.user, classId, 1);
                end
            end
        end
    end

    -- 执行奖励
    BuildingBonusM.doEvent(pos, false, false);

    return true;
end

-- 玩家进入指引关卡的回调
whenEnterNewbieDungeon = function(layer)
    -- 跳过指引模式下，指引关卡第一层需要对指定怪物设置不看守格子
    if SKIP_DUNGEON_GUIDE == 1 and layer == 1 then
        for p = 1, DUNGEON_WIDTH * DUNGEON_HEIGHT do
            local grid = DungeonM.getGridByPos(p);

            -- 获得的怪物
            if  grid:isMonster() and not grid.monster:isDead() then
                local classId = grid.monster:getClassId();
                local dbase = MonsterM.query(classId, "dbase");

                -- 禁止特定怪物对格子的守护
                if dbase["newbie_blind"] == 1 then
                    grid.monster.dbase:set("can_not_lock", 1);
                end
            end
        end
    end
end
